/*
 * Test program for 8x8 LED matrix (single color) and two shift registor
 * 74HC595 
 *
 * HISTORY
 * 2010/9/3  New
 * 2010/9/13 modify code 
 */

/*
 * Copyright (c) 2010 elekid
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#include <Metro.h>


// for 7 segments x 4 display

int LATCH_PIN_K =8;
int CLOCK_PIN_K =6;
int DATA_PIN_K  =7;

int CLOCK_PIN_A =4;
int DATA_PIN_A  =5;

#define SWITCH_ROW_COUNT 100  // loop() count
#define UPDATE_MATRIX_PERIOD 300  // msec



byte Matrix[8] = {
B11111111,
B11111111,
B11111111,
B11111111,
B11111111,
B11111111,
B11111111,
B11111111 };


int data[32] = {
100, 101, 102, 103, 102, 101, 99, 97, 96, 95, 96, 95, 94, 96, 97, 97, 96, 97, 97, 98, 98, 98, 98, 98, 99, 98, 99, 101, 102, 102, 102, 102 };


#define SAMPLING_RATE 2
#define GRAPH_BUF_SIZE   8*SAMPLING_RATE

int P[GRAPH_BUF_SIZE];
int graphBufCounter = 0 ;

int M[8];

int matrixColCounter = 0;


unsigned long switchRowCounter=SWITCH_ROW_COUNT;
Metro updateMatrixTimer = Metro(UPDATE_MATRIX_PERIOD);



void setup()
{
  Serial.begin(9600);
  
  pinMode(LATCH_PIN_K, OUTPUT);  // HC595
  pinMode(CLOCK_PIN_K, OUTPUT);
  pinMode(CLOCK_PIN_A, OUTPUT);
  pinMode(DATA_PIN_K,  OUTPUT);
  pinMode(DATA_PIN_A,  OUTPUT);

}
void loop()
{ 

   displayMatrix();
   
  if ( updateMatrixTimer.check() == 1 ) {
    shiftValues();
    setBufToMatrix(P);
    genMatrixPattern();
  }


}    


void displayMatrix() 
{
  static int cnt=0;

  if (++switchRowCounter < SWITCH_ROW_COUNT ) {
    return;
  }

  switchRowCounter=0;

  digitalWrite(LATCH_PIN_K , LOW);     // HC595
  shiftOut(DATA_PIN_K, CLOCK_PIN_K, MSBFIRST, 0xFF);
  digitalWrite(LATCH_PIN_K , HIGH);    // HC595
  
  // one bit shift for shift registor #1
  if (cnt == 0 ) {
    digitalWrite(DATA_PIN_A, HIGH);
  } else {
    digitalWrite(DATA_PIN_A, LOW);
  }
  digitalWrite(CLOCK_PIN_A, HIGH);
  digitalWrite(CLOCK_PIN_A, LOW);

  // eight bits shift for shift registor #2
  digitalWrite(LATCH_PIN_K , LOW);      // HC595
  shiftOut(DATA_PIN_K, CLOCK_PIN_K, MSBFIRST, Matrix[cnt]);
  digitalWrite(LATCH_PIN_K , HIGH);     // HC595

  if (++cnt >= 8 ) {
    cnt=0;
  }
}

void shiftValues() {

  static int data_pt=0;
  
  for ( int i = GRAPH_BUF_SIZE-1 ; i > 0 ; i--) {
    P[i] = P[i-1];
  }
  P[0] = data[data_pt++];
  if (data_pt >= 32) {
     data_pt=0;
  }
  
  if (graphBufCounter < GRAPH_BUF_SIZE ) {
     graphBufCounter++ ;
  }

}

void setBufToMatrix(int X[] ) {
  matrixColCounter = 0;
  int p = 7;
  for (int i = 0 ; i < graphBufCounter ; i+= SAMPLING_RATE ) {
    M[p--] = X[i];
    matrixColCounter++ ;
  }
}


void genMatrixPattern(){
  
  int max=0;
  int min=0;

  for (int i=0,p=7 ; i < matrixColCounter ; i++,p-- ) {
    if (i==0) {
      max=M[p];
      min=max;
    } else {
      if (max < M[p]) {
        max=M[p];
      }
      if ( min > M[p] ) {
        min=M[p];
      }
    }
  }
  int mid = (max - min ) / 2 + min;

  for ( int i=0 ; i < 8 ; i++ ) {
    Matrix[i] = 0xFF;
  }

  // middle value will be ploted row 4 in matrix
  for (int i=0,p=7 ; i < matrixColCounter ; i++,p-- ) {
    int r = 3 + M[p] - mid ;
    if (r > 7 ) {
      r = 7;
    } else if ( r < 0 ) {
      r = 0;
    }
    Matrix[r] = Matrix[r] ^ (1 << p ); // XOR
  }
}
